package multiNyID.Main;

/*
 * class MultiNyID
 *
 * An Java3D NyARToolkit example using multiple markers and models,
 * that reports position and rotation information.
 * NYARToolkit is available at:
 * http://nyatla.jp/nyartoolkit/wiki/index.php?NyARToolkit%20for%20Java.en
 * JMF also required:
 * http://java.sun.com/javase/technologies/desktop/media/jmf/
 * NCSA Portfolio is used to load the models. It is available at:
 * http://fivedots.coe.psu.ac.th/~ad/jg/ch9/
 * -----------------------------------------------------------------------------
 * Based On NyARToolkit The Java edition ARToolKit class library.
 * modified from class MultiNyAR - Andrew Davison [ad@fivedots.coe.psu.ac.th]
 *
 * @author whe_green@yahoo.co.id
 * Analisis Metode Occlusion Based Pada Augmented Reality
 * Studi Kasus Interaksi dengan Objek Virtual Secara Realtime
 * Menggunakan Gerakan Tangan
 *
 * Institut Teknologi Telkom
 * Fakultas Informatika 2007
 * Bandung Indonesia
 *
 * nyargreen.wordpress.com
 */



import multiNyID.BehaviorCamera.MarkersBehaviorNyID;
import multiNyID.Detector.DetectMarkersNyID;
import multiNyID.MarkerModel.MarkerModelNyID;
import multiNyID.MarkerModel.MarkerGroup;
import multiNyID.Objek.objekJ3D;
import java.awt.*;
import javax.swing.*;

import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;

import jp.nyatla.nyartoolkit.java3d.utils.*;
import jp.nyatla.nyartoolkit.NyARException;
import multiNyID.Interaksi.InteraksiInterface;
import multiNyID.Interaksi.IntroOcclusion;



public class Demo extends JFrame implements MainInterface
{
  private final String PARAMS_FNM = "src/Data/camera_para.dat";

  private static final int PWIDTH = 320;   // size of panel
  private static final int PHEIGHT = 240; 

  private static final double SHAPE_SIZE = 0.02; 

  private static final int BOUNDSIZE = 100;  // larger than world

  private J3dNyARParam cameraParams;
  private JTextArea statusTA;
  private BranchGroup sceneBG;
  private objekJ3D o;


  public Demo()
  {
    super("Multi Marker");

    cameraParams = readCameraParams(PARAMS_FNM);

    Container cp = getContentPane();
    
    sceneBG = new BranchGroup();
    // create a JPanel in the center of JFrame
    JPanel p = new JPanel();
    p.setLayout( new BorderLayout() );
    p.setPreferredSize( new Dimension(PWIDTH, PHEIGHT) );
    cp.add(p, BorderLayout.CENTER);

    // put the 3D canvas inside the JPanel
    p.add(createCanvas3D(), BorderLayout.CENTER);

    // add status field to bottom of JFrame
    statusTA = new JTextArea(7, 10);   // updated by DetectMarkers object (see createSceneGraph())
    statusTA.setEditable(false);
//    cp.add(statusTA, BorderLayout.SOUTH);

    // configure the JFrame
    setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
    pack();
    setVisible(true);
    }  // end of MultiNyAR()



  private J3dNyARParam readCameraParams(String fnm)
  {
    J3dNyARParam cameraParams = null;  
    try {
      cameraParams = new J3dNyARParam();
      cameraParams.loadARParamFromFile(fnm);
      cameraParams.changeScreenSize(PWIDTH, PHEIGHT);
    }
    catch(NyARException e)
    {  System.out.println("Could not read camera parameters from " + fnm);
       System.exit(1);
    }
    return cameraParams;
  }  // end of readCameraParams()



  private Canvas3D createCanvas3D()
  /* Build a 3D canvas for a Universe which contains
     the 3D scene and view 
            univ --> locale --> scene BG
                          |
                           ---> view BG  --> Canvas3D
                              (set up using camera cameraParams)
   */
  { 
    Locale locale = new Locale( new VirtualUniverse() );
    locale.addBranchGraph( createSceneGraph() );   // add the scene

    // get the preferred graphics configuration for the default screen
    GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();

    Canvas3D c3d = new Canvas3D(config);

    locale.addBranchGraph( createView(c3d) );  // add view branch

    return c3d;
  }  // end of createCanvas3D()



  private BranchGroup createSceneGraph()
  /* The scene graph:
         sceneBG 
               ---> lights
               |
               ---> bg
               |
               -----> tg1 ---> model1  
               -----> tg2 ---> model2 
               |
               ---> behavior  (controls the bg and the tg's of the models)
  */
  { 
      
    lightScene(sceneBG);              // add lights

    Background bg = makeBackground();
    sceneBG.addChild(bg);             // add background

    o = new objekJ3D();
    final BranchGroup tranG1 = o.Pointer(1);
    final BranchGroup tranG2 = o.Pointer(1);
    final BranchGroup tranG3 = o.Pointer(1);
    final BranchGroup tranG4 = o.Pointer(1);
    tranG1.setCapability(BranchGroup.ALLOW_DETACH);

    //bikin detect markers
    InteraksiInterface interaksi = new IntroOcclusion();
    DetectMarkersNyID detectMarkers = new DetectMarkersNyID(this,interaksi);

    final double ukuranGame = 0.46; //o.92 --> 32cm  (8x1,15)
    double ukuranBidak = ukuranGame/8;
    // objek buat marker pointer
    final BranchGroup ptr1 = o.Pointer(1);
    final BranchGroup pointerPapan = o.Pointer(1);
    final BranchGroup ptr2 = o.Pointer(2);//catur

    MarkerGroup pointer = new MarkerGroup();
        MarkerModelNyID mm5 = new MarkerModelNyID(5,ptr1,0.01, new Vector3d(), 0.05);
        pointer.addMarkerModel(mm5);
    sceneBG.addChild( mm5.getMoveTg() );

    MarkerGroup pointer2 = new MarkerGroup();
        MarkerModelNyID mm6 = new MarkerModelNyID(6,ptr2,0.01, new Vector3d(), 0.05);
        pointer2.addMarkerModel(mm6);
    sceneBG.addChild( mm6.getMoveTg() );


//        final BranchGroup g1 = o.Gambar("src/models/gambar/1.1.1.jpg");
        final BranchGroup g1 = o.Gambar("src/models/gambar/1.1.1.jpg");
//        catur_dark_rook.3DS
//        mm4.tambahSlide(g1, 0.5);
        final BranchGroup g2 = o.Gambar("src/models/gambar/1.1.2.jpg");
//        mm4.tambahSlide(g2, 0.5);
        final BranchGroup g3 = o.Gambar("src/models/gambar/1.2.1.jpg");
//        mm4.tambahSlide(g3, 0.5);
        final BranchGroup g4 = o.Gambar("src/models/gambar/1.2.2.jpg");
//        mm4.tambahSlide(g4, 0.5);
        final BranchGroup g5 = o.Gambar("src/models/gambar/1.3.1.jpg");
//        mm4.tambahSlide(g3, 0.5);
        final BranchGroup g6 = o.Gambar("src/models/gambar/1.3.2.jpg");
//        mm4.tambahSlide(g4, 0.5);
        final BranchGroup g7 = o.objek3DLoader("catur_dark_king.3DS");
        
    MarkerGroup mg11 = new MarkerGroup();
        MarkerModelNyID mm1 = new MarkerModelNyID(1,g7,ukuranGame/2,new Vector3d(),0.08);
        mg11.addMarkerModel(mm1);
    sceneBG.addChild( mm1.getMoveTg() );

    MarkerGroup mg22 = new MarkerGroup();
        MarkerModelNyID mm2 = new MarkerModelNyID(2,g2,ukuranGame/2,new Vector3d(),0.08);
        mg22.addMarkerModel(mm2);
    sceneBG.addChild( mm2.getMoveTg() );

    MarkerGroup mg33 = new MarkerGroup();
        MarkerModelNyID mm3 = new MarkerModelNyID(3,g3,ukuranGame/2,new Vector3d(),0.08);
        mg33.addMarkerModel(mm3);
    sceneBG.addChild( mm3.getMoveTg() );

    MarkerGroup mg44 = new MarkerGroup();
        MarkerModelNyID mm4 = new MarkerModelNyID(4,g4,ukuranGame/2,new Vector3d(),0.08);
        mg44.addMarkerModel(mm4);
    sceneBG.addChild( mm4.getMoveTg() );

    MarkerGroup mg77 = new MarkerGroup();
        MarkerModelNyID mm7 = new MarkerModelNyID(7,g5,ukuranGame/2,new Vector3d(),0.08);
        mg77.addMarkerModel(mm7);
    sceneBG.addChild( mm7.getMoveTg() );

    MarkerGroup mg88 = new MarkerGroup();
        MarkerModelNyID mm8 = new MarkerModelNyID(8,g6,ukuranGame/2,new Vector3d(),0.08);
        mg88.addMarkerModel(mm8);
    sceneBG.addChild( mm8.getMoveTg() );

    //masukin data markergroup ke detectmarker
    detectMarkers.addMarkerGroup(mg11);
    detectMarkers.addMarkerGroup(mg22);
    detectMarkers.addMarkerGroup(mg33);
    detectMarkers.addMarkerGroup(mg44);    
    detectMarkers.addMarkerGroup(mg77);
    detectMarkers.addMarkerGroup(mg88);


    detectMarkers.addMarkerGroup(pointer); //aplikasi catur
    detectMarkers.addMarkerGroup(pointer2);//catur
    
    
    //set marker pointer
    detectMarkers.setPointer(5);
    detectMarkers.setPointer2(6);
    // create a NyAR multiple marker behaviour
    sceneBG.addChild( new MarkersBehaviorNyID(cameraParams, bg, detectMarkers) );
    
    sceneBG.compile();       // optimize the sceneBG graph
    return sceneBG;
  }  // end of createSceneGraph()



  private void lightScene(BranchGroup sceneBG)
  /* One ambient light, 2 directional lights */
  {
    Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
    BoundingSphere bounds = new BoundingSphere(new Point3d(0,0,0), BOUNDSIZE); 

    // Set up the ambient light
    AmbientLight ambientLightNode = new AmbientLight(white);
    ambientLightNode.setInfluencingBounds(bounds);
    sceneBG.addChild(ambientLightNode);

    // Set up the directional lights
    Vector3f light1Direction  = new Vector3f(-1.0f, -1.0f, -1.0f);
       // left, down, backwards 
    Vector3f light2Direction  = new Vector3f(1.0f, -1.0f, 1.0f);
       // right, down, forwards

    DirectionalLight light1 =  new DirectionalLight(white, light1Direction);
    light1.setInfluencingBounds(bounds);
    sceneBG.addChild(light1);

    DirectionalLight light2 = new DirectionalLight(white, light2Direction);
    light2.setInfluencingBounds(bounds);
    sceneBG.addChild(light2);
  }  // end of lightScene()



  private Background makeBackground()
  // the background will be the current image captured by the camera
  { 
    Background bg = new Background();
    BoundingSphere bounds = new BoundingSphere();
    bounds.setRadius(10.0);
    bg.setApplicationBounds(bounds);
    bg.setImageScaleMode(Background.SCALE_FIT_ALL);
    bg.setCapability(Background.ALLOW_IMAGE_WRITE);  // so can change image

    return bg;
  }  // end of makeBackground()



  private BranchGroup createView(Canvas3D c3d)
  // create a view graph using the camera parameters
  {
    View view = new View();
    ViewPlatform viewPlatform = new ViewPlatform();
    view.attachViewPlatform(viewPlatform);
    view.addCanvas3D(c3d);

    view.setPhysicalBody(new PhysicalBody());
    view.setPhysicalEnvironment(new PhysicalEnvironment());

    view.setCompatibilityModeEnable(true);
    view.setProjectionPolicy(View.PERSPECTIVE_PROJECTION);
    view.setLeftProjection( cameraParams.getCameraTransform() );   // camera projection

    TransformGroup viewGroup = new TransformGroup();
    Transform3D viewTransform = new Transform3D();
    viewTransform.rotY(Math.PI);   // rotate 180 degrees
    viewTransform.setTranslation(new Vector3d(0.0, 0.0, 0.0));   // start at origin
    viewGroup.setTransform(viewTransform);
    viewGroup.addChild(viewPlatform);

    BranchGroup viewBG = new BranchGroup();
    viewBG.addChild(viewGroup);

    return viewBG;
  }  // end of createView()



  public void setStatus(String msg)
  // called from DetectMarkers
  {
    statusTA.setText(msg);
  }  // end of setStatus()

    public BranchGroup getSceneBG() {
        return sceneBG;
    }

  // ------------------------------------------------------------

  public static void main(String args[])
  {  new Demo();  }  
    
} // end of MultiNyAR class
